Chapter 4: Loops

In programming, it is often very useful do carry out a the same action for a series of different items. You might, for instance, want to go through a list of words and count and print the number of characters in each word. Now, you could do this for each word individually and access every word, one item at a time


In [ ]:
my_fruits = ["apple", "pear", "peach", "banana", "peach", "cherry", "orange", "kiwi"]
print(len(my_fruits[0]))
print(len(my_fruits[1]))
print(len(my_fruits[2]))
# and so on...
print(len(my_fruits[-2]))
print(len(my_fruits[-1]))

Needless to say, this is rather cumbersome. Luckily, Python provides the so-called for-statements for this. The for loop allows us to iterate through any iteratable object, such as a list, and do the same thing with each of its elements. The basic format of a for-statement is:

for a_single_item in an_iterable_something:
    do_something_with(a_single_item)

That almost reads like English. We can print all letters of the word banana as follows:


In [ ]:
for letter in "banana":
    print(letter)

The code in the loop is executed as many times as their are letters, with a different value for the variable letter at each iteration. (Read the previous sentence again, until you fully understand it.)

Likewise, we can print all the items that are contained in a list:


In [ ]:
colors = ["yellow", "red", "green", "blue", "purple"]
for color in colors:
    print(color)

Since dictionaries are iterable objects as well, we can iterate through our good reads collection as well. This will iterate over the keys of a dictionary:


In [ ]:
for book in good_reads:
    print(book)

DIY

The function len() returns the length of an iterable item:


In [ ]:
len("banana")
  • We can use this function to print the length of each word in the color list. Write your code in the box below:

In [ ]:
colors = ["yellow", "red", "green", "blue", "purple"]
# insert your code here
  • Now write a small program that iterates through the list colors and appends all colors that contain the letter r to the list colors_with_r. (Tip: use the append() function!)

In [ ]:
colors = ["yellow", "red", "green", "blue", "purple"]
colors_with_r = []
# insert you code here

for color in colors:
    l = len(color)
    colors_with_r.append(l)
    print(colors_with_r)

DIY

We have already covered a lot of ground. Now it is time to put some of the things that we have learned together. The following quiz might be quite hard and we would be very impressed if you get it right!

What we want you to do is write code that counts how often the letter a occurs in a text. You cannot do this, however, on the basis of the text itself. Instead, you need to do this on the basis of a frequency dictionary of the test. In this dictionary frequency_dictionary, keys are words and values are the frequencies. Assign your value to the variable number_of_words_as.


In [ ]:
frequency_dictionary = {"Beg": 1, "Goddard's": 1, "I": 3, "them": 2, "absent": 1, "already": 1,
                          "alteration": 1, "amazement": 2, "appeared": 1, "apprehensively": 1, 
                          "associations": 1, 'clever': 1, 'clock': 1, 'composedly': 1, 
                          'deeply': 7, 'do': 7, 'encouragement': 1, 'entrapped': 1,
                          'expressed': 1, 'flatterers': 1, 'following': 12, 'gone': 9, 
                          'happening': 4, 'hero': 2, 'housekeeper': 1, 'ingratitude': 1, 
                          'like': 1, 'marriage': 15, 'not': 25, 'opportunities': 1,
                          'outgrown': 1, 'playfully': 2, 'remain': 1, 'required': 2, 
                          'ripening': 1, 'slippery': 1, 'touch': 1, 'twenty-five': 1,
                          'ungracious': 2, 'unwell': 1, 'verses': 1, 'yards': 5}
number_of_as = 0
print(number_of_as != 0)


# insert your code here

for word in frequency_dictionary:
    if 'a' in word:
        cnt = 0
        for character in word:
            if character == 'a':
                cnt += 1
        freq = frequency_dictionary[word]
        number_of_as += freq*cnt
        

print(number_of_as)

# if your code is correct, the following line should print True!
#print(number_of_as == 42)
while loop

There is also another form of looping in Python: the while loop. This is a loop that is tied to a logical expression. A while loop will run as long the specified expression is evaluated to be True. Check out the following example to see how this works:


In [ ]:
number = 5
while number < 21:
    number += 3
    print(number)
What we have learned

Here is an overview of the new concepts, statements and functions we have learned in this section. Again, go through the list and make sure you understand them all.

  • loop
  • for statement
  • while statement
  • iterable objects
  • variable assignment in a for loop

Iterables, Iteration & Loops

Tuples & Sets

Lists and dictionaries are hugely important data structures and you will see a lot of them. They are almost always combined with the power of iteration using either for loops or other methods.

In addition to these data structures, there are two others which should be mentioned, these are tuples and sets. Lists, sets, tuples, dictionaries and even strings are often called iterables, as they are all collections over which can be iterated.

Tuples are ordered collections like lists, but they are immutable. Once created, nothing can be added, inserted, deleted or substituted. The main advantage is that they can be faster than lists, which is interesting if you have to process a lot of data. The syntax for creating a tuple involves round brackets (). For example:


In [ ]:
fruittuple = ('banana','apple','pear')
print(fruittuple)
print(fruittuple[0])

Does notice a difference between the way Python prints lists, and the way it prints tuples to your screen? The following would have worked for lists, but does not for tuples (nor strings as we have seen before):


In [ ]:
#fruittuple[0] = 'orange' # will raise an error, tuples are immutable!
for fruit in fruittuple:
    print(fruit)

A set is an unordered data collection in which an each element can only occur once, elements can be appended or deleted. It is unordered so this implies that you never really know in what order you get the elements when you iterate over the set. The syntax for creating a set is {}. This is not to be confused with dictionaries, those take key: value pairs where sets just take single elements.


In [ ]:
fruitset = {'banana', 'apple', 'pear'}
fruitset.add('banana') # will have no effect, banana already exists
print(fruitset)
fruitset.add('orange')
print(fruitset)

Note that the order of the elements maybe different from the order you initialised the fruitset. This is because order has no meaning in the context of sets and neither in that of dictionaries.

In the previous chapter you learnt how to convert strings that contains numbers to integers, and how to turn integers and floats to strings. Such a kind of type casting can also be done for iterables, allowing you to turn almost any iterable into any other.


In [ ]:
fruitlist = ['banana', 'apple', 'pear', 'banana', 'pear', 'kiwi']
fruitset = set(fruitlist)
print(fruitset)

for fruit in fruitset:
    print(fruit)

sorted() and reverse()

Often you want to iterate over your data in a sorted manner. The sorted() function will take any iterable and return the elements in sorted order. For strings this is alphabetical order, for numbers this is numerical order.


In [ ]:
fruits = ['banana', 'apple', 'pear']
for fruit in sorted(fruits):
    print(fruit)

Reverse order is also possible by using reversed(), which simply returns the elements in any iterable in reverse order:


In [ ]:
for fruit in reversed(fruits):
    print(fruit)

DIY

  • Given a list of words, output only the ones that are palindromes. As you know, a palindrome is a word that does not change when read backwards. If you need an extra challenge, try to print the palindromes in alphabetic order!

In [ ]:
words = ['bicycle', 'radar', 'origin', 'tie', 'level', 'poop', 'solar', 'nun']
# insert your code here

palindromes = []

for original_word in words:
    reversed_word = ''
    for character in reversed(original_word):
        reversed_word += character
    if original_word == reversed_word:
        palindromes.append(original_word)

print(palindromes)
Extra Brownie points!
  • There are also words which are not palindromes, but when reversed another existing word emerges. Consider the words stressed and desserts. We give you a text that contains a few of them, output all pairs that occur in the text (regardless of case), but exclude words with a length of one.

In [ ]:
text = "I just live for desserts , I really love them . My dog does too . I saw he ate mine . I was very stressed because of that . If dogs steal desserts God can't be real , for it is pure evil ." 
# insert your code here

min(), max() and sum()

When dealing with lists of numbers, there are three functions which come in handy:


In [ ]:
numbers = [1, 2, 3, 4, 5]
print(min(numbers))
print(max(numbers))
print(sum(numbers))

DIY

  • Compute the average of numbers:

In [ ]:
# insert your code here

Final Exercises Chapter 4

Inspired by Think Python by Allen B. Downey (http://thinkpython.com), Introduction to Programming Using Python by Y. Liang (Pearson, 2013). Some exercises below have been taken from: http://www.ling.gu.se/~lager/python_exercises.html.

  • Define a sentence and split it into words along whitespace. Now fill a dictionary that holds the frequencies (value) for each word (key) in the sentence. You should first check whether a word is already present in your dictionary. If it is, augment its frequency. Else, you should first initialize its frequency.

In [ ]:
# fill dictionary code
  • By now, you already know that Python has the len() function built-in, but can you write yourself a code block that prints the length of the string lengthy_word that you will define? First use a for loop; then try to achieve the same results with a while loop, but watch out that you don't get stuck an infinite loop!

In [ ]:
# lengthy word (1) code
  • Have another look at the string variable lenghty_word that you defined in the previous exercices. Can you write a code block that fills a dictionary char_freqs containing the frequency of the different individual characters in length_word?

In [ ]:
# lengty_word (2) code
  • Let's have yet another at lengthy_word. Can you write code that creates the dictionary next_char, holding for each first occurence of a character (key) the next character in the word as value. If the character is already in the dictionary, do nothing and if you're dealing with the last character in the word, add "Last word!" as value to the dictionary for this character.

In [ ]:
# lengthy_word (3) code
  • Write a code block that defines a list of integers and prints them as a histogram to the screen. For example, for histogram = [4, 9, 7, 2, 16, 8, 3], the code should print the following:

++++

+++++++++

+++++++

++

++++++++++++++++

++++++++

+++


In [ ]:
# histogram
  • "99 Bottles of Beer" is a traditional song in the United States and Canada. It is popular to sing on long trips, as it has a very repetitive format which is easy to memorize, and can take a long time to sing. The song's simple lyrics are as follows: "99 bottles of beer on the wall, 99 bottles of beer. Take one down, pass it around, 98 bottles of beer on the wall." The same verse is repeated, each time with one fewer bottle. The song is completed when the singer or singers reach zero. Your task here is write a Python code block capable of generating all the verses of the song. Use a counter integer variable and a while loop. Make sure that your loop will come to an end and that the inflection of the word bottle is adapted to the counter!

In [ ]:
# bottles of beer
  • The third person singular verb form in English is distinguished by the suffix -s, which is added to the stem of the infinitive form: run -> runs. A simple set of rules can be given as follows: "If the verb ends in y, remove it and add ies. If the verb ends in o, ch, s, sh, x or z, add es. By default just add s." Your task in this exercise is to write a code block which given a verb in infinitive form, prints its third person singular form. Test your function with words like "try", "brush", "run" and "fix". Can you think of verbs for which your code doesn't work? Check out the string method .endswith() online!

In [ ]:
# verbs code
  • ROT13 is a way to encode secret messages in cryptography. The name comes from Julius Caesar, who used it to communicate with his generals. ROT13 ("rotate by 13 places") is a widely used example of a Caesar cipher. The idea is to rotate or augment the position of each character in the alphabet with thirteen places. Your task in this exercise is to implement an encoder/decoder of ROT-13. For this, you will need to create a list containing each letter in the (lowercase) roman alphabet as well as the whitespace character. Next, you will have to create an encode_dict and a decode_dict. Once you're done, you will be able to read the following secret message: "Pnrfne pvcure? V zhpu cersre Pnrfne fnynq!" (Hint: you can use .index() to retrieve the position of an item in a list!)

In [ ]:
# Caesar code

Congrats: you've reached the end of Chapter 4! Ignore the code block below; it's only here to make the page prettier.


In [1]:
from IPython.core.display import HTML
def css_styling():
    styles = open("styles/custom.css", "r").read()
    return HTML(styles)
css_styling()


Out[1]: